﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MvcEngine.Core.Configuration;
using MvcEngine.Core.Helpers;
using MvcEngine.Core;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Reflection;
using MvcEngine.Core.Exceptions;
using System.IO;
using System.Xml.Linq;
using System.Xml;
using System.Web;

namespace MvcEngine.LinqToSqlProvider
{
    public class DataContextFactory : DisposableResource, IDataContextFactory
    {
        protected readonly string connectionString;
        protected DataContext context;

        public DataContextFactory(IConnectionString connectionString)
        {
            Guard.ThrowIfNull(connectionString, "connectionString");
            this.connectionString = connectionString.Value;
        }

        private static XmlMappingSource CreateMappingSource() 
        {
            var factories = IoC.ResolveAll<IDataContextService>();

            XmlDocument doc = new XmlDocument();

            bool isFirst = true;

            foreach (var item in factories)
            {
                if (isFirst)
                {
                    doc.Load(item.GetMappingFile());
                    isFirst = false;
                }
                else
                {
                    XmlDocument childDoc = new XmlDocument();
                    childDoc.Load(item.GetMappingFile());


                    foreach (XmlNode node in childDoc.DocumentElement.ChildNodes)
                    {
                        XmlNode n = doc.ImportNode(node, true);
                        doc.DocumentElement.AppendChild(n);
                    }
                }
            }
            return XmlMappingSource.FromXml(doc.OuterXml);
        }

        public virtual DataContext Get()
        {
            if (context == null)
            {
                return new DataContext(connectionString, CreateMappingSource());
            }
            return context;
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (context != null)
                {
                    context.Dispose();
                }
            }

            base.Dispose(disposing);
        }

        public void DisposeDataContext()
        {
            if (context != null)
            {
                context.Dispose();
                context = null;
            }
        }
    }
}
